#ifndef _I_API_DEVICE_H_
#define _I_API_DEVICE_H_

#include "U_api_Types.h"
#include "S_api_Struct.h"
#include "E_api_Enum.h"

class I_api_Device;
class I_api_DeviceChild;

class I_api_Blob;
class I_api_Resource;
class I_api_Buffer;
class I_api_Texture_2D;

class I_api_View;
class I_api_ShaderResourceView;
class I_api_RenderTargetView;
class I_api_DepthStencilView;
class I_api_UnorderedAccessView;
class I_api_Framebuffer;

class I_api_VertexShader;
class I_api_PixelShader;
class I_api_Program;

class I_api_RasterizerState;
class I_api_DepthStencilState;

class I_api_InputLayout;

class I_api_Device
{
protected:
	friend class C_gl_Texture_2D;
	friend class I_api_DepthStencilState;

	I_api_InputLayout * m_pCurrentInputLayout;

	virtual	u32	ComparisonToOpenGL(E_api_Comparison_Func func) const { return 0; } ;
	virtual	u32	StencilopToOpenGL(E_api_Stencil_Op op) const { return 0; } ;
	virtual	u32	FormatToOpenGLInternal(E_api_Format format) const { return 0; } ;
	virtual	u32	FormatToOpenGLFormat(E_api_Format format) const { return 0; } ;
	virtual	u32	FormatToOpenGLType(E_api_Format format) const { return 0; } ;

public:
	I_api_Device(){}
	I_api_Device(void	*pDevice){}
	virtual ~I_api_Device(){}

	virtual void		Set(void	*pDevice) = 0; 
	virtual void	*	Get(void) = 0;

	//////////////////////////////////////////////////////////////////////////
	/// Create Calls
	//////////////////////////////////////////////////////////////////////////	
	virtual bool		CreateBuffer(const S_api_BufferDesc *pDesc, const S_api_Subresource_Data *pInitialData, I_api_Buffer **ppBuffer) = 0;
	virtual	bool		CreateTexture2D(const S_api_Texture2D_Desc *pDesc, const S_api_Subresource_Data *pInitialData, I_api_Texture_2D **ppTexture2D)=0;
	
	virtual bool		CreateVertexShader(const void *pShaderBytecode, int BytecodeLength, I_api_VertexShader **ppVertexShader) = 0;
	virtual bool		CreatePixelShader(const void *pShaderBytecode, int BytecodeLength, I_api_PixelShader **ppPixelShader) = 0;
	
	virtual bool		CreateProgram(I_api_VertexShader *pVertexShader, I_api_PixelShader *pPixelShader, I_api_Program **ppProgram, I_api_Blob **ppErrorMsg) = 0;
	
	virtual	bool		CreateShaderResourceView(I_api_Resource * pResource, const S_api_ShaderResourceView_Desc *pDesc, I_api_ShaderResourceView **ppSRView)=0;
	virtual	bool		CreateRenderTargetView(I_api_Resource * pResource, const S_api_RenderTargetView_Desc *pDesc, I_api_RenderTargetView **ppRTView)=0;
	virtual	bool		CreateDepthStencilView(I_api_Resource * pResource, const S_api_DepthStencilView_Desc *pDesc, I_api_DepthStencilView **ppDepthStencilView)=0;	
	virtual	bool		CreateUnorderedAccessView(I_api_Resource *	pResource, const S_api_UnorderedAccessView_Desc *pDesc, I_api_UnorderedAccessView **ppUnordererdAccessView)=0;
	virtual	bool		CreateFramebuffer(int nRenderTargetView, I_api_RenderTargetView **pRenderTargetView, I_api_DepthStencilView *pDepthStencilView, I_api_Framebuffer **ppFramebuffer)=0;
	
	virtual	bool		CreateRasterizerState(const	S_api_Rasterizer_Desc	* pDesc, I_api_RasterizerState	**ppRasterizerState)=0;
	virtual	bool		CreateDepthStencilState(const S_api_DepthStencilState * pDesc, I_api_DepthStencilState **ppDepthStencilState)=0;

	//////////////////////////////////////////////////////////////////////////
	/// Draw Calls
	//////////////////////////////////////////////////////////////////////////	
	virtual void		DrawIndexed(int IndexCount, int StartIndexLocation, int BaseVertexLocation)=0;
	virtual void		Draw(int VertexCount, int StartVertexLocation)=0;

	virtual void		Flush()=0;

	//////////////////////////////////////////////////////////////////////////
	/// VS Calls
	//////////////////////////////////////////////////////////////////////////
	virtual void		VSSetShader(I_api_VertexShader * pVertexShader)=0;

	//////////////////////////////////////////////////////////////////////////
	/// GS Calls
	//////////////////////////////////////////////////////////////////////////
	//virtual void	GSSetShader(I_api_GeometryShader * pGeometryShader)=0;


	//////////////////////////////////////////////////////////////////////////
	/// IA Calls
	//////////////////////////////////////////////////////////////////////////
	//virtual void	IAGetIndexBuffer(I_api_Buffer **pIndexBuffer, E_api_Format *Format, int *Offset);
	virtual void		IAGetInputLayout(I_api_InputLayout **ppInputLayout)  { *ppInputLayout = m_pCurrentInputLayout; }
	virtual void		IASetInputLayout(I_api_InputLayout *pInputLayout) { m_pCurrentInputLayout = pInputLayout; } ;
	virtual void		IASetVertexBuffers(int StartSlot, int NumBuffers, I_api_Buffer **ppVertexBuffers, int *pStrides, int *pOffsets)=0;

	//////////////////////////////////////////////////////////////////////////
	/// PS Calls
	//////////////////////////////////////////////////////////////////////////
	virtual void		PSSetShader(I_api_PixelShader * pPixelShader)=0;


	//////////////////////////////////////////////////////////////////////////
	/// Program Calls
	//////////////////////////////////////////////////////////////////////////
	virtual void		SetProgram(I_api_Program * pProgram)=0;

	//////////////////////////////////////////////////////////////////////////
	/// OM calls
	//////////////////////////////////////////////////////////////////////////
	virtual	void		OMSetRenderTargets(int NumViews, I_api_RenderTargetView *const *ppRenderTargetViews, I_api_DepthStencilView **ppDepthStencilView)=0;
	virtual	void		OMGetRenderTargets(int NumViews, I_api_RenderTargetView			 **ppRenderTargetViews, I_api_DepthStencilView **ppDepthStencilView)=0;
	virtual	void		OMSetFramebuffer(I_api_Framebuffer	*pFramebuffer)=0;
	virtual	void		OMSetDepthStencilState(I_api_DepthStencilState *pDepthStencilState, u32 StencilRef)=0;

	//////////////////////////////////////////////////////////////////////////
	/// RS calls
	//////////////////////////////////////////////////////////////////////////
	virtual	void		RSSetState(I_api_RasterizerState	*pRasterizerState)=0;

	//////////////////////////////////////////////////////////////////////////
	/// Clear calls
	//////////////////////////////////////////////////////////////////////////
	virtual	void		ClearRenderTargetView(I_api_RenderTargetView *pRenderTargetView, const float ColorRGBA[4])=0;
	virtual	void		ClearDepthStencilView(I_api_DepthStencilView *pDepthStencilView, u32 ClearFlags, float Depth, u8 Stencil)=0;
	virtual	void		ClearFramebuffer(I_api_Framebuffer *pFramebuffer, u32 ClearMask, const float Color[4], float Depth, u8 Stencil)=0;
};

#endif